package com.example.mq.mqserver.core;

import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;
import java.util.Map;
import java.util.UUID;

/**
 * 表示一个要传递的消息
 * 此处的Message对象，是需要能够在网络上传输，并且也需要能写入到文件中
 * 此处就需要针对Message进行序列化和反序列化
 * 此处使用标准库自带的序列化/反序列化操作
 */
@Data
public class Message implements Serializable {
    //验证版本
    private static final long serialVersionUID=1L;
    //这两个是Message核心部分
    //属性
    private BasicProperties basicProperties=new BasicProperties();
    //正文
    private byte[] body;

    //下面两个属性是辅助属性
    //Message后续会存储到文件中（需要持久化的）
    //一个文件中会存储很多消息 【offsetBeg,offsetEnd)
    //如何找到某个消息在文件中的具体位置呢？使用下面两个偏移量来进行表示
    //这两个属性并不需要被序列化 (transient) 报错到文件中，此事消息一旦被写入文件之后，所在的位置就固定了，并不需要单独存储
    //这两属性存在的目的，主要就是为了让内存中的Message对象，能够快速的 找到对应的硬盘上的Message的位置
    private transient long offsetBeg=0;//消息数据的开头距离文件开头的位置偏移（字节）
    private transient long offsetEnd=0;//消息数据的结尾距离文件开头的位置偏移（字节）
    //使用这个属性来表示该消息在文件中是否是有效的消息（针对文件中的消息，如果删除，使用逻辑删除的方式）
    //0x1表示有效，0x0表示无效
    private byte isValid=0x1;

    //创建一个工厂方法，让工厂方法帮我们封装一下创建Message对象的过程
    //这个方法中创建的Message对象，或自动生成唯一的MessageId
    //唯一routingKey和basicProperties里的routingKey冲突，以外面的为主
    public static Message createMessageWithId(String routingKey,BasicProperties basicProperties,byte[] body){
        Message message=new Message();
        if(basicProperties!=null){
            message.setBasicProperties(basicProperties);
        }
        //此处生成的MessageId以M-作为前缀，与其他生成的UUID区分
        message.setMessageId("M-"+ UUID.randomUUID());
        message.setRoutingKey(routingKey);
        message.body=body;
        //此处是把核心设置出来（body 和 basicProperties）
        //而 offsetBeg offsetEnd isValid,则是消息持久化的时候才会用到，再把消息写入文件之前再进行设定
        //此处只是在内存中创建一个Message对象
        System.out.println("------"+message);
        return message;
    }

    public String getMessageId(){
        return basicProperties.getMessageId();
    }

    public void setMessageId(String messageId){
        basicProperties.setMessageId(messageId);
    }

    public String getRoutingKey(){
        return basicProperties.getRoutingKey();
    }

    public void setRoutingKey(String routingKey){
        basicProperties.setRoutingKey(routingKey);
    }

    public int getDeliverMode(){
        return basicProperties.getDeliverMode();
    }

    public void setDeliverMode(int deliverMode){
        basicProperties.setDeliverMode(deliverMode);
    }
}
